package stackmachine;

import stackmachine.command.*;

import java.util.LinkedList;

public class StackMachine {
    private LinkedList<StackItem> stack;
    private LinkedList<StackItem> out;

    public StackMachine() {
        stack = new LinkedList<StackItem>();
        out = new LinkedList<StackItem>();
    }

    public static Command[] convertCommands(Object[] commands) {
        Command[] result = new Command[commands.length];
        for (int i = 0; i < commands.length; ++i) {
            if (commands[i] instanceof String) {
                String str = (String) commands[i];
                if (str.equals("DUP")) {
                    result[i] = new DupCommand();
                }
                else if (str.equals("DEC")) {
                    result[i] = new DecCommand();
                }
                else if (str.equals("IF")) {
                    result[i] = new IfCommand();
                }
                else if (str.equals("DROP")) {
                    result[i] = new DropCommand();
                }
                else if (str.equals("JUMP")) {
                    result[i] = new JumpCommand();
                }
                else if (str.equals("MOVE")) {
                    result[i] = new MoveCommand();
                }
                else if (str.equals("OUT")) {
                    result[i] = new OutCommand();
                }
                else if (str.equals("*")) {
                    result[i] = new MulCommand();
                }
                else if (str.equals("+")) {
                    result[i] = new SumCommand();
                }
                else if (str.equals("CHR")) {
                    result[i] = new ChrCommand();
                } else {
                    throw new IllegalArgumentException("Unsupported command " + str);
                }
            } else {
                result[i] = new NumberCommand((Integer)commands[i]);
            }
        }

        return result;
    }

    public void processCommands(Command[] commands) {
        stack.clear();
        while (!out.isEmpty()) {
            stack.addLast(out.pollLast());
        }

        IP ip = new IP();
        while (ip.getValue() < commands.length) {
            if (!commands[ip.getValue()].commit(stack, out, ip)) {
                System.out.print("OUT BY BREAK");
                break;
            }
        }
    }

    public void printOut() {
        System.out.println("OUT: ");
        for (StackItem item : out) {
            System.out.print(item.toString() + "");
        }
        System.out.println();
    }
}
